package com.xsy.middleware.controller;

import cn.hutool.core.io.FileUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xsy.middleware.entity.FileRecord;
import com.xsy.middleware.service.DataBackService;
import com.xsy.middleware.utils.ResultVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

/**
 * @Description: 定时同步crm文件到服务器
 * @Author: 黎炎松
 * @Date: 2024/4/19 14:42
 */
@Slf4j
@Controller
public class SyncCrmTableFile {

    //@Value("${saveFileUrl}")
    private static String localSaveFileUrl;

    @Autowired
    private DataBackService dataBackService;

    static {
        System.out.println("localSaveFileUrl======= > 获取本地路径");
        String absolutePath = new File("").getAbsolutePath();
        localSaveFileUrl = absolutePath + File.separator + "crm_file";
        System.out.println("localSaveFileUrl======= > " + localSaveFileUrl);
    }

    /**
     * 根据表名处理文件同步
     * @param tableName
     * @param isUpdate 是否更新 0：否 1：是
     */
    public ResultVo syncCrmTableFile(String tableName, int isUpdate) {
        JSONObject tableData = new JSONObject();
        try {
            log.info("同步crm表格文件开始: {}", tableName);

            // 根据表名读取有变更的数据
            if (StringUtils.isBlank(tableName)) {
                log.info("表名不可为空");
                return ResultVo.error("表名不可为空");
            }

            // 判断库中表是否存在
            if (!dataBackService.isTableExist(tableName)) {
                log.info("同步文件失败，数据库中不存在当前表  ==== > {}", tableName);
                return ResultVo.error("同步文件失败，数据库中不存在当前表  ==== > " + tableName);
            }

            // 查询配置表信息
            tableData = dataBackService.getDataBackup(tableName);
            if (tableData == null) {
                log.info("查询配置表数据为空");
                return ResultVo.error("查询配置表数据为空");
            }

            // 时间范围获取
            Long startSyncTime = tableData.getLong("lastSyncFileTime__c"); // 同步开始时间 （上次同步的结束时间）
            Long endSyncTime = System.currentTimeMillis(); // 同步结束时间 （当前时间）

            // 查询配置表明细
            JSONArray tableFileList = dataBackService.getDataBackupDetailByType(tableData.getLong("id"), 3);
            log.info("配置表需要同步的文件字段 : {}", tableFileList);
            if (tableFileList.size() <= 0) {
                log.info("当前配置表没有需要同步的文件字段 : {}", tableName);
                // 更新文件修改时间
                updateDataBackup(tableData, endSyncTime);
                return ResultVo.success("当前配置表没有需要同步的文件字段 : " + tableName);
            }

            // 获取查询的字段
            ArrayList<String> fieldList = new ArrayList<>();
            fieldList.add("id");
            for (Object o : tableFileList) {
                JSONObject obj = (JSONObject) o;
                fieldList.add(obj.getString("fieldApiKey__c"));
            }
            String fileJoin = String.join(",", fieldList);

            // 查询数据库中数据
            String sql = "";
            if (isUpdate == 1) {
                // 更新只需要更新部分数据
                sql = "select %s from %s where updatedAt between %s and %s";
                sql = String.format(sql, fileJoin, tableName, startSyncTime, endSyncTime);
            } else {
                sql = "select %s from %s";
                sql = String.format(sql, fileJoin, tableName);
            }

            List<HashMap<String, Object>> tableDataList = dataBackService.selectTableData(sql);
            if (tableDataList.size() <= 0) {
                log.info("暂无需要同步的数据 : {}", tableName);
                // 更新文件修改时间
                updateDataBackup(tableData, endSyncTime);
                return ResultVo.success("暂无需要同步的数据 : " + tableName);
            }

            // 对数据进行保存
            List<FileRecord> fileRecordAddList = new ArrayList<>();
            List<Long> moduleIdList = new ArrayList<>();
            for (int i = 0; i < tableDataList.size(); i++) {
                HashMap<String, Object> tData = tableDataList.get(i);

                // 判断如果是只有id一个值则不进行处理
                if (tData.size() == 1) {
                    continue;
                }

                Long tableId = Long.valueOf(tData.get("id").toString());
                moduleIdList.add(tableId);
                log.info("处理需要同步文件的数据 : {}", tableId);

                // 删除本地文件
                List<Long> tempModuleIdList =  new ArrayList<>();
                tempModuleIdList.add(tableId);
                List<String> fileUrlList = dataBackService.queryFileUrlByModule(tableName, tempModuleIdList);
                for (String fileUrl : fileUrlList) {
                    File file = new File(fileUrl);
                    if (file.exists()) {
                        file.delete();
                    }
                }

                // 遍历文件字段 获取需要处理的文件
                for (int j = 0; j < tableFileList.size(); j++) {
                    JSONObject tableFileData = tableFileList.getJSONObject(j);

                    String fileKey = tableFileData.getString("fieldApiKey__c");
                    String fileName = tableFileData.getString("fieldName__c");
                    if (tData.get(fileKey) == null) {
                        continue;
                    }

                    // 处理字段的文件值
                    String fileData = tData.get(fileKey).toString();
                    if (StringUtils.isNotBlank(fileData)) {
                        JSONArray fileList = JSONArray.parseArray(fileData);

                        // 文件下载到本地
                        for (Object o : fileList) {
                            JSONObject obj = (JSONObject) o;
                            String fileUrl = obj.getString("url");

                            String downFileUrl = downLoadFromUrl(tableName, fileUrl);

                            // 构建插入需要到的值
                            FileRecord fileRecord = new FileRecord();
                            fileRecord.setId(UUID.randomUUID().toString().replace("-", ""));
                            fileRecord.setModule(tableName);
                            fileRecord.setModuleId(tableId);
                            fileRecord.setModuleFileName(fileName);
                            fileRecord.setModuleFileKey(fileKey);
                            fileRecord.setFileUrl(downFileUrl);
                            fileRecord.setCrmFileData(fileData);
                            fileRecord.setCreateTime(System.currentTimeMillis());
                            fileRecordAddList.add(fileRecord);
                        }

                    }

                }

                // 100 条 批量进行保存
                if (fileRecordAddList.size() >= 100 || (i == tableDataList.size() -1 && fileRecordAddList.size() > 0)) {
                    // 删除数据库文件
                    int delCount = dataBackService.delFileRecordByModule(tableName, moduleIdList);
                    log.info("文件记录批量删除================================{}", delCount);
                    moduleIdList.clear();

                    int insertCount = dataBackService.batchInsertFileRecord(fileRecordAddList);
                    log.info("文件记录批量保存================================{}  ==> {}", insertCount, insertCount);
                    fileRecordAddList.clear();
                }

            }

            // 更新文件修改时间
            updateDataBackup(tableData, endSyncTime);

            log.info("同步数据文件成功 : {}", tableName);
            return ResultVo.success("同步数据文件成功 : " + tableName);

        } catch (Exception e) {
            log.error("定时同步crm文件数据处理异常 : {}", e.getMessage());
            //throw new RuntimeException(e);

            try {
                // 更新配置表数据
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("id", tableData.get("id"));
                jsonObject.put("syncFileStatus__c", 2);
                jsonObject.put("syncFileErrorDesc__c", e.getMessage());
                dataBackService.updateDataBackup(jsonObject);
            } catch (UnsupportedEncodingException ex) {
                throw new RuntimeException(ex);
            }

            return ResultVo.error("定时同步crm文件数据处理异常: " + e.getMessage());
        }
    }

    /**
     * 更新配置表文件修改时间
     * @param tableData
     * @param endSyncTime
     * @return
     * @throws UnsupportedEncodingException
     */
    public ResultVo updateDataBackup(JSONObject tableData, Long endSyncTime) throws UnsupportedEncodingException {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("id", tableData.get("id"));
        jsonObject.put("lastSyncFileTime__c", endSyncTime);
        jsonObject.put("entityType", tableData.get("entityType"));
        jsonObject.put("syncFileStatus__c", 1);
        jsonObject.put("syncFileErrorDesc__c", "");
        ResultVo update = dataBackService.updateDataBackup(jsonObject);
        if (update.getCode() != 200) {
            log.info("更新配置表数据异常 : {}", update.getMsg());
            ResultVo.error("更新配置表数据异常 : " + update.getMsg());
        }
        return ResultVo.success();
    }



    /**
     * @description 从网络URL中下载文件
     */
    public static String downLoadFromUrl(String tableName, String fileUrl) {
        String path = "";
        if (fileUrl == null) {
           return path;
        }
        // 文件名 保持和crm 一致
        String fileName = fileUrl.substring(fileUrl.lastIndexOf("/"));
        try {
            File file = new File(localSaveFileUrl);
            if (!file.exists()) {
                // 创建文件夹
                boolean mkdir = file.mkdir();
                if (!mkdir) {
                    throw new RuntimeException("创建文件夹失败，路径为：" + localSaveFileUrl);
                }
            }
            //log.info("fileName : {}", fileName);
            path = localSaveFileUrl + File.separator + tableName + fileName;
            // 文件下载
            HttpUtil.downloadFile(fileUrl, FileUtil.file(path));
            return path;
        } catch (Exception e) {
            log.info("下载crm文件处理异常 : {}", e.getMessage());
        }
        return path;
    }


}
